package com.qiche.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qiche.aspect.Result;
import com.qiche.common.TokenCache;
import com.qiche.constant.AccountType;
import com.qiche.dto.RegisterDto;
import com.qiche.enums.ResultEnum;
import com.qiche.exception.MySystemException;
import com.qiche.mapper.MerchantMapper;
import com.qiche.mapper.RegionMapper;
import com.qiche.mapper.UserMapper;
import com.qiche.mapper.UserRoleMapper;
import com.qiche.model.*;
import com.qiche.redis.RedisService;
import com.qiche.service.*;
import com.qiche.util.PasswordHelper;
import com.qiche.util.UserUtils;
import com.qiche.vo.MiniHomeStatementDatVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.StringUtil;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by Linzw on 2018/01/24.
 */
@Service("userService")
public class UserServiceImpl extends BaseService<User> implements UserService {
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private RegionMapper regionMapper;
    @Resource
    private MerchantMapper merchantMapper;
    @Autowired
    private RedisService redisService;
    @Autowired
    private InsurancePolicyService policyService;
    @Autowired
    private SubscribeService subscribeService;
    @Autowired
    private CardService cardService;
    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private StoreMemberService storeMemberService;

    /**
     * 用户登录
     * @param username
     * @param password
     * @return
     */
    @Override
    public Result login(String username, String password,boolean rememberMe) {
        boolean exist = isUsernameExist(username);
        if (!exist) {
            return Result.createByErrorMessage("用户名不存在");
        }

        //todo 密码登录MD5
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password,rememberMe);

        try {
            subject.login(token);
            User user = selectByUsername(username);
            //把密码去掉
            user.setPassword(StringUtils.EMPTY);
            Boolean isAdmin=  AccountType.ADMIN==user.getAccountType()?true:false;
            return Result.createBySuccess("登录成功", isAdmin);
        } catch (LockedAccountException lae) {
            token.clear();
            return Result.createByErrorMessage("用户已经被锁定不能登录，请与管理员联系！");
        } catch (AuthenticationException e) {
            token.clear();
            return Result.createByErrorMessage("用户或密码不正确！");
        }
    }

    /**
     * 用户注销
     * @return
     */
    @Override
    public Result<String> logout() {
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.logout();
        } catch (Exception e) {
            return Result.createByErrorMessage("注销失败");
        }
        return Result.createBySuccessMessage("注销成功");
    }

    /**
     * 用户注册
     * @param user
     * @return
     */
    @Override
    public Result<User> register(User user) {
        boolean exist = isUsernameExist(user.getUsername());
        if (exist) {
            return Result.createByErrorMessage("用户名已经存在");
        }

        User currentUser= UserUtils.getCurrentUser();

        //默认为门店类型
        user.setAccountType(AccountType.MERCHANT);
        if(currentUser==null ||AccountType.AGENT==currentUser.getAccountType()){
            user.setRoleId(AccountType.MERCHANT);
        }
        user.setEnable(1);
        //密码加密
        PasswordHelper helper = new PasswordHelper();
        helper.encryptPassword(user);

        int resultCount = userMapper.insert(user);
        //添加 用户 -角色 关联
        if(user.getRoleId() != null){
            UserRole userRole = new UserRole();
            userRole.setRoleid(user.getRoleId().toString());
            userRole.setUserid(user.getId());
            userRoleService.addUserRole(userRole);
        }
        if (resultCount == 0) {
            return Result.createByErrorMessage("注册失败");
        }
        return Result.createBySuccess("注册成功",user);
    }


    /**
     * 忘记密码的验证码校验
     * @param username
     * @param verifyCode
     * @return
     */
    @Override
    public Result<String> forgetCheckVerifyCode(String username,String verifyCode){
        if(StringUtils.isBlank(verifyCode)){
            return Result.createByErrorMessage("请填写验证码");
        }
        boolean exist = isUsernameExist(username);
        if (!exist) {
            return Result.createByErrorMessage("用户名不存在");
        }
        User user = selectByUsername(username);
        // 判断验证码
        // 两种情况：1、根据用户名找到门店预留手机 ,2、使用用户的手机
        String phone="";
        if(StringUtils.isBlank(user.getPhone())){
            Merchant merchant= merchantMapper.selectByPrimaryKey(user.getMerchantId().longValue());
            if(merchant == null || StringUtils.isBlank(merchant.getPhone()) ){
                return Result.createByErrorMessage("该账号没有填写手机号码且未关联门店，无法获取手机号");
            }
            phone=merchant.getPhone();
        }else {
            phone=user.getPhone();
        }
       // String verifyCodeCache = redisManager.getString(phone + "forgetPasswordVerifyCode");
        String verifyCodeCache =  redisService.get(phone + "forgetPasswordVerifyCode").toString();
         boolean isEqual= StringUtils.equals(verifyCode,verifyCodeCache);
         if(isEqual){
             return Result.createBySuccessMessage("验证码校验通过");
             //todo 有个username要返回？
         }else {
             return Result.createByErrorMessage("验证码错误");
         }
    }

    /**
     * 忘记密码的重置密码
     * @param username
     * @param passwordNew
     * @param forgetToken 防止横向越权
     * @return
     */
    @Override
    public Result<String> forgetResetPassword(String username,String passwordNew,String forgetToken){
        if(StringUtils.isBlank(forgetToken)){
            return Result.createByErrorMessage("参数错误,token需要传递");
        }
        boolean exist = isUsernameExist(username);
        if (!exist) {
            return Result.createByErrorMessage("用户名不存在");
        }
        String token= TokenCache.getKey(TokenCache.TOKEN_PREFIX+username);
        if(StringUtils.isBlank(token)){
            return Result.createByErrorMessage("token无效或者过期");
        }
        if(StringUtils.equals(forgetToken,token)){
            User user = selectByUsername(username);
            user.setPassword(passwordNew);
            PasswordHelper helper = new PasswordHelper();
            helper.encryptPassword(user);
           int updateCount= userMapper.updateByPrimaryKeySelective(user);
           if(updateCount>0){
               return Result.createBySuccessMessage("重置密码成功");
           }
        }else{
            return Result.createByErrorMessage("token错误，请重新获取重置密码的token");
        }
        return Result.createBySuccessMessage("重置密码失败");
    }

    /**
     * 根据条件和分页获取用户列表
     * @param user
     * @param page
     * @param limit
     * @return
     */
    @Override
    public PageInfo<User> selectByPage(User user, int page, int limit) {

        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtil.isNotEmpty(user.getUsername())) {
            criteria.andLike("username", "%" + user.getUsername() + "%");
        }
        if (user.getId() != null) {
            criteria.andEqualTo("id", user.getId());
        }
        if (user.getEnable() != null) {
            criteria.andEqualTo("enable", user.getEnable());
        }
        if (user.getMerchantId() != null) {
            criteria.andEqualTo("merchantId", user.getMerchantId());
        }

        // 分页查询
        PageHelper.startPage(page, limit);
        List<User> userList = selectByExample(example);
        return new PageInfo<>(userList);
    }

    /**
     * 根据用户名查找用户
     * @param username
     * @return
     */
    @Override
    public User selectByUsername(String username) {
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username", username);
        List<User> userList = selectByExample(example);
        if (userList.size() > 0) {
            return userList.get(0);
        }
        return null;
    }

    /**
     * 根据ID查找用户
     * @param id
     * @return
     */
    @Override
    public User selectById(Long id) {
        return  userMapper.selectByPrimaryKey(id);
    }

    /**
     * 根据门店ID查找对应的用户
     * @param merchantId
     * @return
     */
    @Override
    public User selectByMerchantId(Integer merchantId) {
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("merchantId", merchantId);
        List<User> userList = selectByExample(example);
        if (userList.size() > 0) {
            return userList.get(0);
        }
        return null;
    }

    /**
     * 检查用户名是否存在
     * @param username
     * @return
     */
    @Override
    public Boolean isUsernameExist(String username) {
        User user = selectByUsername(username);
        if (user == null) {
            return false;
        } else {
            return true;
        }
    }


    /**
     * 根据ID删除用户
     * @param userid
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    public void delUser(Integer userid) {
        // 删除用户表
        mapper.deleteByPrimaryKey(userid);
        // 删除用户角色表
        Example example = new Example(UserRole.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userid", userid);
        userRoleMapper.deleteByExample(example);
    }

    /**
     * 表单提交注册
     * @param dto
     * @return
     */

    @Override
    @Transactional
    public Result<User> register(RegisterDto dto) {

        // 判断用户名
        User user = selectByUsername(dto.getUsername());
        if (user != null) {
            throw new MySystemException(ResultEnum.USER_HAS_EXIST);
        }
        // 判断验证码
        if (StringUtils.isNotBlank(dto.getVerifyCode())) {
            String phone = dto.getPhone();
            String vcode =redisService.get(phone + "registerVerifyCode").toString();
           // String vcode = redisManager.getString(phone + "registerVerifyCode");
            if (vcode == null || !vcode.equals(dto.getVerifyCode())) {
                throw new MySystemException(ResultEnum.VERIFY_CODE_ERROR);
            }
        }

        // 创建门店实体
        Merchant merchant = new Merchant();
        merchant.setAddress(dto.getMerchantAddress());
        merchant.setContacts(dto.getContacts());
        merchant.setRegionId(dto.getRegionId());
        merchant.setName(dto.getMerchantName());
        merchant.setPhone(dto.getPhone());
        merchant.setStatus((byte) 0);
        merchant.setIsActive((byte) 0);
        String regionName = regionMapper.selectByPrimaryKey(dto.getRegionId()).getRegionName();
        merchant.setRegionName(regionName);
        merchantMapper.insert(merchant);

        // 创建用户实体
        User newUser = new User();
        newUser.setEnable(0);
        newUser.setUsername(dto.getUsername());
        newUser.setMerchantId(merchant.getId().intValue());
        newUser.setPassword(dto.getPassword());
        PasswordHelper helper = new PasswordHelper();
        helper.encryptPassword(newUser);
        userMapper.insert(newUser);

        return Result.createBySuccessMessage(ResultEnum.REGISTER_APPLY_SUCCESS.getMsg());


    }


    @Override
    public MiniHomeStatementDatVo getMiniHomeStatement(User user,
                                                       Date startTime,
                                                       Date endTime) {
        Integer merchantId = user.getMerchantId();
        /*----------------新增用户 查询---------------*/
        int membersDateForCount = storeMemberService.countByTimeRange(merchantId, startTime, endTime);

        int membersCount = storeMemberService.countByTimeRange(merchantId, null, null);
        /*----------------保单查询-------------------*/
        List<InsurancePolicy> policies = policyService.selectPolicyMoneyAll(merchantId);

        List<InsurancePolicy> policysDateFor = policies.stream().filter(policie ->
                policie.getCreateTime().getTime() >= startTime.getTime()
                        && policie.getCreateTime().getTime() <= endTime.getTime())
                .collect(Collectors.toList());

        double allPolicyMoney = policies.stream().mapToDouble(InsurancePolicy::getPolicyMoney).sum();
        double policyMoneyDateFor = policysDateFor.stream().mapToDouble(InsurancePolicy::getPolicyMoney).sum();

        int policysDateForCount = policysDateFor.size();
        int policysCount = policies.size();
        /*----------------结算工单查询----------------*/
        List<Subscribe> subscribes = subscribeService.selectAllColseByMerchantId(merchantId);

        List<Subscribe> subscribesDateFor = subscribes.stream().filter(subscribe ->
                subscribe.getCreateTime().getTime() >= startTime.getTime()
                        && subscribe.getCreateTime().getTime() <= endTime.getTime())
                .collect(Collectors.toList());

        double allSubscribesMoney = subscribes.stream().mapToDouble(Subscribe::getProducesMoney).sum();
        double subscribesMoneyDateFor = subscribesDateFor.stream().mapToDouble(Subscribe::getProducesMoney).sum();

        int subscribesCount = subscribes.size();
        int subscribesDateForCount = subscribesDateFor.size();


		/*----------------卡券查询--------------------*/

        List<Card> cards = cardService.selectCardAmountAllByMerchantId(merchantId);

        List<Card> cardsDateFor = cards.stream().filter(card ->
                card.getWriteoffDate().getTime() >= startTime.getTime()
                        && card.getWriteoffDate().getTime() <= endTime.getTime())
                .collect(Collectors.toList());

        double amount = cards.stream().mapToLong(Card::getCardAmount).sum();
        double amountDateFor = cardsDateFor.stream().mapToLong(Card::getCardAmount).sum();

        int cardsCount = cards.size();
        int cardsDateForCount = cardsDateFor.size();


        MiniHomeStatementDatVo miniHomeStatementDatVo = new MiniHomeStatementDatVo();

        miniHomeStatementDatVo.setMembersCount(membersCount);
        miniHomeStatementDatVo.setMembersDateForCount(membersDateForCount);

        miniHomeStatementDatVo.setPolicysCount(policysCount);
        miniHomeStatementDatVo.setPolicysDateForCount(policysDateForCount);
        miniHomeStatementDatVo.setAllPolicyMoney(allPolicyMoney);
        miniHomeStatementDatVo.setPolicyMoneyDateFor(policyMoneyDateFor);

        miniHomeStatementDatVo.setSubscribesCount(subscribesCount);
        miniHomeStatementDatVo.setSubscribesDateForCount(subscribesDateForCount);
        miniHomeStatementDatVo.setAllSubscribesMoney(allSubscribesMoney);
        miniHomeStatementDatVo.setSubscribesMoneyDateFor(subscribesMoneyDateFor);

        miniHomeStatementDatVo.setCardsCount(cardsCount);
        miniHomeStatementDatVo.setCardsDateForCount(cardsDateForCount);
        miniHomeStatementDatVo.setAmount(amount);
        miniHomeStatementDatVo.setAmountDateFor(amountDateFor);

        return miniHomeStatementDatVo;
    }

    @Override
    public PageInfo<User> selectClerksByPage(User user, int page, int limit) {
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtil.isNotEmpty(user.getUsername())) {
            criteria.andLike("username", "%" + user.getUsername() + "%");
        }

        if (user.getEnable() != null) {
            criteria.andEqualTo("enable", user.getEnable());
        }
        if (user.getMerchantId() != null) {
            criteria.andEqualTo("merchantId", user.getMerchantId());
        }

        criteria.andEqualTo("accountType", AccountType.CLERK);

        // 分页查询
        PageHelper.startPage(page, limit);
        List<User> userList = selectByExample(example);
        return new PageInfo<>(userList);
    }


    /**
     * 系统保存用户
     * @param user
     * @return
     */
    @Override
    public Result<User> saveUserBySystem(User user) {
        if(user.getAccountType()== null){
            return Result.createByErrorMessage("未指定账号类型");
        }
        boolean exist = isUsernameExist(user.getUsername());
        if (exist) {
            return Result.createByErrorMessage("用户名已经存在");
        }
        //默认为门店类型
        user.setRoleId(user.getAccountType());
        user.setEnable(1);
        //密码加密
        PasswordHelper helper = new PasswordHelper();
        helper.encryptPassword(user);

        int resultCount = userMapper.insert(user);
        //添加 用户 -角色 关联
        if(user.getRoleId() != null){
            UserRole userRole = new UserRole();
            userRole.setRoleid(user.getRoleId().toString());
            userRole.setUserid(user.getId());
            userRoleService.addUserRole(userRole);
        }
        if (resultCount == 0) {
            return Result.createByErrorMessage("保存失败");
        }
        return Result.createBySuccess("保存成功",user);
    }
}
